package cn.taskservice.common.utils.transcaction;

import org.springframework.context.ApplicationContext;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.function.Supplier;

/**
 * 事务工具类(适用于多个数据源, 使用 ApplicationContext 获取事务管理器)
 * This class provides utility methods for managing transactions across multiple data sources.
 * It uses the ApplicationContext to obtain the transaction manager.
 */
public class TransactionUtil {

    private final ApplicationContext applicationContext;
    private final String transactionTemplateName;
    private final String transactionManagerName;

    private TransactionTemplate transactionTemplate;
    private PlatformTransactionManager transactionManager;

    /**
     * 构造方法
     * Constructor for the TransactionUtil class.

     *
     * @param applicationContext      Spring 上下文, the Spring application context.
     * @param transactionTemplateName 事务模板 Bean 名称, the name of the TransactionTemplate bean.
     * @param transactionManagerName  事务管理器 Bean 名称, the name of the PlatformTransactionManager bean.
     */
    public TransactionUtil(ApplicationContext applicationContext, String transactionTemplateName, String transactionManagerName) {
    // 将传入的 Spring 上下文赋值给类的成员变量 applicationContext
        this.applicationContext = applicationContext;
    // 将传入的事务模板 Bean 名称赋值给类的成员变量 transactionTemplateName
        this.transactionTemplateName = transactionTemplateName;
    // 将传入的事务管理器 Bean 名称赋值给类的成员变量 transactionManagerName
        this.transactionManagerName = transactionManagerName;
    }

    /**
     * 获取 TransactionTemplate（懒加载）
 *  Lazy loads the TransactionTemplate instance.
     *
 * 该方法用于懒加载 TransactionTemplate 实例。懒加载是一种设计模式，
 * 用于延迟对象的初始化，直到真正需要使用它时才进行。这样可以提高性能，
 * 避免不必要的资源占用。
     * This method initializes the TransactionTemplate instance only when it is needed, improving performance and avoiding unnecessary resource usage.
     */
    private TransactionTemplate getTransactionTemplate() {
    // 检查 transactionTemplate 是否为 null，如果是则进行初始化
        if (transactionTemplate == null) {
        // 从 applicationContext 中获取名为 transactionTemplateName 的 TransactionTemplate bean
        // applicationContext 是 Spring 应用上下文，用于管理 Spring 容器中的 bean
        // transactionTemplateName 是 TransactionTemplate bean 的名称
        // TransactionTemplate.class 指定了要获取的 bean 的类型
            transactionTemplate = applicationContext.getBean(transactionTemplateName, TransactionTemplate.class);
        }
    // 返回 transactionTemplate 实例
        return transactionTemplate;
    }

    /**
     * 获取 PlatformTransactionManager（懒加载）
     * Lazy loads the PlatformTransactionManager instance.
     */
    private PlatformTransactionManager getTransactionManager() {
        if (transactionManager == null) {
            transactionManager = applicationContext.getBean(transactionManagerName, PlatformTransactionManager.class);
        }
        return transactionManager;
    }

    /**
     * 使用 TransactionTemplate 执行事务（无返回值）
     * Executes a transaction using TransactionTemplate without returning a value.
     */
    public void executeWithTransactionTemplate(Runnable action) {
        getTransactionTemplate().executeWithoutResult(status -> {
            try {
                action.run();
            } catch (Exception e) {
                status.setRollbackOnly();
                throw new RuntimeException("事务执行失败，已回滚", e);
            }
        });
    }

    /**
     * 使用 TransactionTemplate 执行事务（有返回值）
     * Executes a transaction using TransactionTemplate and returns a value.
     */
    public <T> T executeWithTransactionTemplate(Supplier<T> action) {
        return getTransactionTemplate().execute((TransactionCallback<T>) status -> {
            try {
                return action.get();
            } catch (Exception e) {
                status.setRollbackOnly();
                throw new RuntimeException("事务执行失败，已回滚", e);
            }
        });
    }

    /**
     * 使用 PlatformTransactionManager 手动管理事务（无返回值）
     * Manually manages a transaction using PlatformTransactionManager without returning a value.
     */
    public void executeWithTransactionManager(Runnable action) {
        executeWithTransactionManager(action, 5, TransactionDefinition.PROPAGATION_REQUIRED);
    }

    /**
     * 使用 PlatformTransactionManager 手动管理事务（有返回值）
     * Manually manages a transaction using PlatformTransactionManager and returns a value.
     */
    public <T> T executeWithTransactionManager(Supplier<T> action) {
        return executeWithTransactionManager(action, 5, TransactionDefinition.PROPAGATION_REQUIRED);
    }

    /**
     * 使用 PlatformTransactionManager 手动管理事务（无返回值，带传播行为和超时）
     * Manually manages a transaction using PlatformTransactionManager without returning a value, with propagation behavior and timeout.
     */
    public void executeWithTransactionManager(Runnable action, int timeout, int propagationBehavior) {
        doExecuteWithTransactionManager(() -> {
            action.run();
            return null;
        }, timeout, propagationBehavior);
    }

    /**
     * 使用 PlatformTransactionManager 手动管理事务（有返回值，带传播行为和超时）
     * Manually manages a transaction using PlatformTransactionManager and returns a value, with propagation behavior and timeout.
     */
    public <T> T executeWithTransactionManager(Supplier<T> action, int timeout, int propagationBehavior) {
        return doExecuteWithTransactionManager(action, timeout, propagationBehavior);
    }

    /**
     * 事务执行通用方法，减少代码重复
     * Common method for executing transactions to reduce code duplication.
     */
    public <T> T doExecuteWithTransactionManager(Supplier<T> action, int timeout, int propagationBehavior) {
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(propagationBehavior);
        def.setTimeout(timeout);
        TransactionStatus status = getTransactionManager().getTransaction(def);
        try {
            T result = action.get();
            getTransactionManager().commit(status);
            return result;
        } catch (Exception e) {
            getTransactionManager().rollback(status);
            throw new RuntimeException("事务执行失败，已回滚", e);
        }
    }
}
